#include"config.h"

#define MATRIX_RCLK (0x01<<20)
#define MATRIX_SRCLK (0x01<<17)
#define MATRIX_SI_X (0x01<<18)
#define MATRIX_SI_Y (0x01<<19)
#define MATRIX_MAT 0xfffffc03
#define MATRIX_NUMBER 0x04

uint16 display_buffer[16]; //汉字缓存数组
uint8 display_pit = 0x00;  //Scan函数中用来控制显示的指针
uint16 latic_line_bit = 0x00;  //控制列     
//字库
const uint16 font[][16]={0x0002,0x7FF2,0x2812,0x2412,0x2212,0x21FE,0x2012,0x2012,0x2012,0x21FE,0x2212,0x2212,0x2212,0x7FF2,0x0002,0x0000,
0xFFFB,0x807B,0xEDDB,0xEDDB,0x001B,0xEDDB,0xEDDB,0xDDDB,0xDDFB,0xBEEB,0xFEF7,0xC003,0xFEFF,0xFEFF,0x0001,0xFFFF,
0xF9BF,0xC7AF,0xF7B7,0xF7B7,0xF7BF,0x0001,0xF7BF,0xF7B7,0xF1D7,0xC7CF,0x37DF,0xF7AF,0xF66D,0xF7F5,0xD7F9,0xEFFD,
0xFF07,0xC0FF,0xFEFF,0x8001,0xFC3F,0xF2CF,0xCEF1,0x3EFB,0xE00F,0xFDDF,0xFDBF,0xFB03,0xFBFB,0xF7FB,0xEFD7,0xDFEF};

uint32 AD_num;          //AD值

void PortInit(){
    //点阵屏端口初始化
	PINSEL1 &= MATRIX_MAT; //引脚连接模块设置，这里选择P0.17～P0.20作GPIO 
	IO0DIR |= MATRIX_SRCLK; //方向输出 
	IO0DIR |= MATRIX_RCLK; 
	IO0DIR |= MATRIX_SI_X; 
	IO0DIR |= MATRIX_SI_Y; 

}

void sendData(uint16 row,uint16 line){
    //点阵发送数据
	uint8 tmp;
	IO0CLR|=MATRIX_RCLK ;
	for(tmp=0x00;tmp<16;tmp++)
	{
		IO0CLR |= MATRIX_SRCLK;
        if((row & 0x8000) == 0)  //-----行输入
        {
            IO0CLR |= MATRIX_SI_X;    //发送 低电平
        }        
        else 
        {
            IO0SET |= MATRIX_SI_X;    //发送 高电平
        }
        if((line & 0x8000) == 0) //只有符合目标输入列的列才会使能
        {
            IO0CLR |= MATRIX_SI_Y;    //发送 低电平
        }
        else
        {
            IO0SET |= MATRIX_SI_Y;    //发送 高电平
        }   
        IO0SET |= MATRIX_SRCLK;  //SCK = 1
        row = row << 1;
        line = line << 1;
	}
	IO0SET |= MATRIX_RCLK ;
}

void Scan(){
    //每调用一次该函数，就会将缓冲数组里的一个字列打印到点阵屏上
    display_pit = display_pit % 16; //使列循环
    latic_line_bit = ~(0x8000 >> display_pit); //控制列
    sendData(display_buffer[display_pit],latic_line_bit); 
    display_pit ++;  
}

void LaticPrint(uint32 num){
    //移动字符，根据num的值来决定显示哪一个字符
    uint8 temp;
    //如果num大于字符总数，则从0开始找
    if(num>=MATRIX_NUMBER){
        num=num%MATRIX_NUMBER;
    }
    for(temp=0;temp<16;temp++){
        display_buffer[temp]=font[num][temp];
    }
}

void __irq IRQ_Time0Interrupt(){
    //定时器中断服务程序
    Scan();  //点阵扫描
    
    T0IR = 0x01; //复位MR0中断
    VICVectAddr=0x00;//清除地址
}

void timer0_init(){
    //定时器初始化
	T0TC=0;
	T0PR=0;
	T0MCR=0x03;
	T0MR0=Fpclk/1000;
	VICIntSelect &= 0xffffffef; 
	VICVectCntl2 =0x20|4;
	VICVectAddr2 =(uint32)IRQ_Time0Interrupt;
	VICIntEnable=(1<<4);
	T0TCR = 0x01;
}

void __irq IRQ_ADInterrupt(){
    //AD中断服务程序
    //获取AD值
    AD_num=ADDR;
    AD_num=AD_num>>6;
    AD_num=AD_num&0x000003ff;
    //输出AD值
    LaticPrint(AD_num);
    VICVectAddr=0x00;
}

void AD_interruptInit(){
    //AD中断初始化
    VICintSelect &= 0xfffbffff;
    VICVectCntl3=0x32;
    VICVectAddr3=(uint32)IRQ_ADInterrupt;
    VICIntEnable=0x00040000;
}

void AD_Init(){
    //AD端口初始化
    PINSEL1 |= 0x00400000;
    ADCR=(1<<0)                 |
        ((Fpclk/1000000)<<8)    |
        (1<<16)                 |
        (2<<17)                 |
        (1<<21)                 |
        (0<<22)                 |
        (1<<24)                 |
        (0<<27);
    AD_interruptInit();
}


int main(){
	PortInit();
    AD_Init();
	timer0_init();
	while(1);
}